// index.ts
import type {
  AxiosInstance,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";
import axios from "axios";
import type { RequestConfig, RequestInterceptors, Res } from "./types";
import type { LoadingInstance } from "element-plus/es/components/loading/src/loading";
import { ElLoading } from "element-plus";
import NProgress from "nprogress"; // 进度条
let loading: LoadingInstance;

class Request {
  // axios 实例
  instance: AxiosInstance;
  // 拦截器对象
  interceptorsObj?: RequestInterceptors;

  // 拦截器执行顺序 接口请求 -> 实例请求 -> 全局请求 -> 实例响应 -> 全局响应 -> 接口响应
  constructor(config: RequestConfig) {
    this.instance = axios.create(config);
    this.interceptorsObj = config.interceptors;
    this.instance.interceptors.request.use(
      (res: InternalAxiosRequestConfig) => {
        // const userStore = useUserStoreHook();
        // if (userStore.token) {
        // 	console.log(Date.now())
        //   config.headers['Authorization'] = userStore.token
        // config.headers.Authorization = userStore.token;
        // console.log(config)
        // }
        if (config.isShowing || config.isShowing === undefined) {
          loading = ElLoading.service({});
          NProgress.start();
        }
        return res;
      },
      (err: any) => err
    );

    // 使用实例拦截器
    this.instance.interceptors.request.use(
      this.interceptorsObj?.requestInterceptors,
      this.interceptorsObj?.requestInterceptorsCatch
    );
    this.instance.interceptors.response.use(
      this.interceptorsObj?.responseInterceptors,
      this.interceptorsObj?.responseInterceptorsCatch
    );
    // 全局响应拦截器保证最后执行
    this.instance.interceptors.response.use(
      // 因为我们接口的数据都在res.data下，所以我们直接返回res.data
      (res: AxiosResponse) => {
        const { code, msg } = res.data;
        if (code === "00000") {
          NProgress.done();
          return res.data;
        }
        ElMessage.error(msg || "系统出错");
        NProgress.done();
        return Promise.reject(new Error(msg || "Error"));
      },
      (error: any) => {
        if (error.response.data) {
          const { code, msg } = error.response.data;
          // token 过期，跳转登录页
          if (code === "A0230") {
            ElMessageBox.confirm("当前页面已失效，请重新登录", "提示", {
              confirmButtonText: "确定",
              type: "warning",
            }).then(() => {
              localStorage.clear(); // @vueuse/core 自动导入
              window.location.href = "/";
            });
          } else {
            ElMessage.error(msg || "系统出错");
          }
        }
        return Promise.reject(error.message);
      }
    );
  }
  request<T = Res>(config: RequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      //对config处理
      if (config.interceptors?.requestInterceptors) {
        config = config.interceptors.requestInterceptors(
          config as InternalAxiosRequestConfig
        );
      }
      //对res数据处理
      this.instance
        .request<T, any>(config)
        .then((res) => {
          if (config.interceptors?.responseInterceptors) {
            res = config.interceptors.responseInterceptors(res);
          }
          loading?.close();
          resolve(res);
        })
        .catch((error) => {
          loading?.close();
          reject(error);
        });
    });
  }
  get<T = Res>(config: RequestConfig): Promise<T> {
    return this.request({ ...config, method: "GET" });
  }

  post<T = Res>(config: RequestConfig): Promise<T> {
    return this.request({ ...config, method: "POST" });
  }
}
export default Request;
